<template>
  <div class="messages-area" ref="messagesContainerRef" @contextmenu.prevent>
    <div
      v-for="msg in messages"
      :key="msg.message_id"
      class="message-row"
      :class="{ 
        'message-sent': !msg.isReceived, 
        'message-received': msg.isReceived
      }"
      @contextmenu.prevent="handleMessageRightClick($event, msg)"
    >
      <!-- 接收的消息：头像在左侧 -->
      <q-avatar
        v-if="msg.isReceived"
        class="message-avatar"
        size="36px"
        :style="getAvatarStyle(msg.from_user_id)"
      >
        {{ getUserInitial(msg.from_user_id) }}
      </q-avatar>
      
      <!-- 消息气泡容器 -->
      <div class="message-bubble-wrapper" :class="{ 'bubble-sent': !msg.isReceived, 'bubble-received': msg.isReceived }">
        <!-- 时间显示在消息上方 -->
        <div class="message-time-header">
          <span class="message-time">{{ formatTime(msg.timestamp) }}</span>
        </div>
        <!-- 消息气泡 -->
        <div class="message-bubble" :class="{ 'bubble-sent': !msg.isReceived, 'bubble-received': msg.isReceived }">
          <MarkdownMessage
            v-if="msg.message || msg.file_url"
            :content="msg.message || ''"
            :is-sent="!msg.isReceived"
            :file-url="msg.file_url"
            :file-name="msg.file_name"
            :file-type="msg.file_type"
            :message-content-type="(msg as any).message_content_type"
          />
        </div>
      </div>
      
      <!-- 发送的消息：头像在右侧 -->
      <q-avatar
        v-if="!msg.isReceived"
        class="message-avatar"
        size="36px"
        :style="getAvatarStyle(currentUserId)"
      >
        {{ getUserInitial(currentUserId) }}
      </q-avatar>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { useQuasar } from 'quasar'
import MarkdownMessage from './MarkdownMessage.vue'
import { updateReadSequence } from '../services/im-chat'
import { useChatStore } from '../stores/chat'
import { getAvatarStyle } from '@/utils/avatar'

const props = defineProps<{
  messages: Array<{
    message_id: string
    isReceived: boolean
    from_user_id: string
    message?: string
    file_url?: string
    file_name?: string
    file_type?: string
    message_content_type?: number // 消息内容类型：1=文本, 2=图片, 3=文件
    timestamp: number
    sequence?: number
  }>
  currentUserId: string
  formatTime: (timestamp: number) => string
  getUserInitial: (userId: string | null) => string
  getUserName?: (userId: string | null) => string // 获取用户显示名称（用于群聊消息显示发送者名字）
  chatId?: string
  chatType?: number
  chatSequence?: number // 聊天记录中的最新消息序列号（用于更新已读序列号）
  readSequence?: number // 聊天记录中的已读消息序列号（用于初始化lastReadSequence）
}>()

const messagesContainerRef = ref<HTMLElement | null>(null)
const chatStore = useChatStore()
const $q = useQuasar()
const selectedMessageIds = ref<Set<string>>(new Set())
let lastReadSequence = 0
let isUpdatingReadSequence = false

let scrollTimeout: ReturnType<typeof setTimeout> | null = null
let currentChatId: string | undefined = undefined // 跟踪当前的 chatId，用于检测切换

// 检查是否需要滚动（消息是否超出容器高度）
const needsScrolling = () => {
  if (!messagesContainerRef.value) return false
  
  const container = messagesContainerRef.value
  const scrollHeight = container.scrollHeight
  const clientHeight = container.clientHeight
  
  // 如果内容高度小于等于容器高度，说明不需要滚动
  return scrollHeight > clientHeight
}

// 检查是否滚动到底部
const checkScrollToBottom = () => {
  if (!messagesContainerRef.value) return false
  
  const container = messagesContainerRef.value
  const threshold = 50 // 距离底部50px内认为已到底部（更严格的判断）
  const scrollTop = container.scrollTop
  const scrollHeight = container.scrollHeight
  const clientHeight = container.clientHeight
  const distanceToBottom = scrollHeight - scrollTop - clientHeight
  
  const isAtBottom = distanceToBottom <= threshold
  
  return isAtBottom
}

// 更新已读序列号
// 打开聊天窗口即视为已读（参考主流IM做法，如微信、Telegram等）
const updateReadSequenceIfNeeded = async () => {
  if (!props.chatId) {
    return
  }
  if (isUpdatingReadSequence) {
    return
  }
  
  // 重要：只有在用户真正查看这个聊天时才更新已读序列号
  // 检查消息列表容器是否可见（在视口中）
  if (messagesContainerRef.value) {
    const rect = messagesContainerRef.value.getBoundingClientRect()
    const isVisible = rect.width > 0 && rect.height > 0
    if (!isVisible) {
      return
    }
  }
  
  // 优先使用聊天记录中的 sequence（这是服务器端的最新消息序列号）
  // 即使消息列表为空，只要有 chatSequence，也应该更新已读序列号
  let currentSequence: number | null = null
  
  if (props.chatSequence) {
    // 使用聊天记录中的 sequence（最准确，因为这是服务器端的最新序列号）
    currentSequence = props.chatSequence
  } else if (props.messages && props.messages.length > 0) {
    // 回退方案：从消息列表中获取最后一条消息的时间戳
    // 优先使用接收的消息（离线消息），如果没有接收的消息，使用最后一条消息
    const receivedMessages = props.messages.filter(msg => msg.isReceived)
    if (receivedMessages.length > 0) {
      // 如果有接收的消息，使用最后一条接收消息的时间戳
      const latestReceivedMessage = receivedMessages[receivedMessages.length - 1]
      currentSequence = latestReceivedMessage.sequence || latestReceivedMessage.timestamp_ms || latestReceivedMessage.timestamp
    } else {
      // 如果没有接收的消息，使用最后一条消息的时间戳
      const latestMessage = props.messages[props.messages.length - 1]
      currentSequence = latestMessage.sequence || latestMessage.timestamp_ms || latestMessage.timestamp
    }
  }
  
  if (!currentSequence) {
    // 如果没有序列号，说明确实没有消息，不需要更新
    return
  }
  
  // 检查是否切换了聊天（chatId 变化）
  const isChatSwitched = currentChatId !== props.chatId
  if (isChatSwitched) {
    // 如果切换了聊天，重置 lastReadSequence 为当前聊天的 readSequence
    lastReadSequence = props.readSequence ?? 0
    currentChatId = props.chatId
  }
  
  // 如果已经是最新的，不需要更新
  // 注意：如果切换了聊天，即使 currentSequence <= lastReadSequence，也要尝试更新（因为 lastReadSequence 可能已经重置）
  if (!isChatSwitched && currentSequence <= lastReadSequence) {
    return
  }
  
  // 打开聊天窗口即视为已读，不需要滚动到底部（参考主流IM做法）
  try {
    isUpdatingReadSequence = true
    console.log('📖 更新已读序列号:', {
      chatId: props.chatId,
      currentSequence,
      lastReadSequence,
      chatSequence: props.chatSequence,
      messageCount: props.messages?.length || 0,
    })
    await updateReadSequence(props.chatId, currentSequence)
    lastReadSequence = currentSequence
    
    // 更新已读序列号后，触发聊天列表刷新
    // 通过自定义事件通知父组件刷新聊天列表
    window.dispatchEvent(new CustomEvent('readSequenceUpdated', {
      detail: { chatId: props.chatId, readSequence: currentSequence }
    }))
  } catch (error: any) {
    console.error('更新已读序列号失败:', error)
  } finally {
    isUpdatingReadSequence = false
  }
}

// 监听滚动事件（仅用于UI显示，不再用于已读标记）
const handleScroll = () => {
  // 滚动时显示滚动条
  if (messagesContainerRef.value) {
    messagesContainerRef.value.classList.add('scrolling')
    
    // 清除之前的定时器
    if (scrollTimeout) {
      clearTimeout(scrollTimeout)
    }
    
    // 滚动停止后1秒隐藏滚动条
    scrollTimeout = setTimeout(() => {
      if (messagesContainerRef.value) {
        messagesContainerRef.value.classList.remove('scrolling')
      }
    }, 1000)
  }
}

// 监听消息变化（不再自动标记为已读，只保留必要的状态更新）
// 已读标记只能通过手动调用 markAsRead() 方法触发
watch(() => props.messages, () => {
  // 消息变化时不做任何自动标记操作
  // 已读标记必须由用户主动打开聊天窗口时通过 markAsRead() 手动触发
}, { deep: true })

// 监听chatId变化，重置lastReadSequence（不再自动标记为已读）
watch(() => props.chatId, (newChatId, oldChatId) => {
  // 如果 chatId 从 null 变为有效值，说明聊天已加载完成
  if (oldChatId === null && newChatId) {
    // 使用当前聊天的 read_sequence 初始化 lastReadSequence
    lastReadSequence = props.readSequence ?? 0
    currentChatId = newChatId
  } else if (newChatId && newChatId !== oldChatId) {
    // chatId 变化（切换聊天），使用新聊天的 read_sequence 初始化
    lastReadSequence = props.readSequence ?? 0
    currentChatId = newChatId
  } else if (newChatId && newChatId === oldChatId) {
    // chatId 没变，但可能 readSequence 或 chatSequence 更新了，也要更新 currentChatId
    currentChatId = newChatId
  }
  // 不再自动标记为已读，必须由用户主动打开聊天窗口时通过 markAsRead() 手动触发
})

// 监听readSequence变化，更新lastReadSequence（不再自动标记为已读）
watch(() => props.readSequence, (newReadSequence, oldReadSequence) => {
  if (newReadSequence !== undefined && newReadSequence !== null && props.chatId) {
    // 如果 chatId 匹配，更新 lastReadSequence
    // 注意：当切换聊天时，readSequence 可能会变化，应该更新
    if (currentChatId === props.chatId) {
      // 如果 lastReadSequence 是 0（初始值）或者新的 readSequence 更大，就更新
      // 或者如果 readSequence 从无到有，也要更新
      if (lastReadSequence === 0 || newReadSequence > lastReadSequence || (oldReadSequence === null || oldReadSequence === undefined)) {
        lastReadSequence = newReadSequence
      }
    }
  }
  // 不再自动标记为已读，必须由用户主动打开聊天窗口时通过 markAsRead() 手动触发
})

// 监听chatSequence变化（不再自动标记为已读）
watch(() => props.chatSequence, () => {
  // chatSequence 变化时不做任何自动标记操作
  // 已读标记必须由用户主动打开聊天窗口时通过 markAsRead() 手动触发
})

onMounted(() => {
  if (messagesContainerRef.value) {
    messagesContainerRef.value.addEventListener('scroll', handleScroll)
    // 初始化 lastReadSequence 和 currentChatId
    lastReadSequence = props.readSequence ?? 0
    currentChatId = props.chatId
    // 不再自动标记为已读，必须由用户主动打开聊天窗口时通过 markAsRead() 手动触发
  }
})

onUnmounted(() => {
  if (messagesContainerRef.value) {
    messagesContainerRef.value.removeEventListener('scroll', handleScroll)
  }
  if (scrollTimeout) {
    clearTimeout(scrollTimeout)
  }
})

// 手动触发已读序列号更新（供父组件调用）
const markAsRead = () => {
  // 打开窗口即视为已读（参考主流IM做法）
  updateReadSequenceIfNeeded()
}

// 处理消息右键点击
const handleMessageRightClick = (event: MouseEvent, msg: any) => {
  // 选中当前右键点击的消息
  selectedMessageIds.value.clear()
  selectedMessageIds.value.add(msg.message_id)
  
  // 直接显示删除确认对话框
  deleteSelectedMessages()
}

// 删除选中的消息
const deleteSelectedMessages = async () => {
  if (selectedMessageIds.value.size === 0) return
  
  const messageIds = Array.from(selectedMessageIds.value)
  
  $q.dialog({
    title: '确认删除',
    message: `确定要删除选中的 ${messageIds.length} 条消息吗？此操作仅删除本地缓存，不会影响服务器端。`,
    cancel: true,
    persistent: true
  }).onOk(async () => {
    try {
      const deletedCount = await chatStore.deleteMessages(messageIds)
      selectedMessageIds.value.clear()
      
      $q.notify({
        type: 'positive',
        message: `已删除 ${deletedCount} 条消息`,
        position: 'top',
        timeout: 2000
      })
    } catch (error: any) {
      console.error('删除消息失败:', error)
      $q.notify({
        type: 'negative',
        message: `删除消息失败: ${error.message || '未知错误'}`,
        position: 'top',
        timeout: 3000
      })
    }
  })
}

// 监听 chatId 变化，清空选择
watch(() => props.chatId, () => {
  selectedMessageIds.value.clear()
})

defineExpose({
  messagesContainerRef,
  markAsRead
})
</script>

<style lang="sass" scoped>
.messages-area
  flex: 1
  overflow-y: auto
  padding: 20px
  display: flex
  flex-direction: column
  gap: 12px
  background: #EDEDED
  position: relative

.message-row
  display: flex
  align-items: flex-start
  gap: 10px
  max-width: 100%
  animation: fadeIn 0.2s ease

  &.message-sent
    justify-content: flex-end

@keyframes fadeIn
  from
    opacity: 0
    transform: translateY(8px)
  to
    opacity: 1
    transform: translateY(0)

.message-avatar
  flex-shrink: 0
  color: white
  font-weight: 500
  font-size: 14px

.message-bubble-wrapper
  max-width: 70%
  display: flex
  flex-direction: column
  
  &.bubble-sent
    align-items: flex-end
  
  &.bubble-received
    align-items: flex-start

.message-time-header
  display: flex
  align-items: center
  margin-bottom: 6px
  padding: 0 2px
  min-height: 16px
  
  .message-time
    color: rgba(0, 0, 0, 0.45)
    font-size: 11px
    font-weight: 400
    white-space: nowrap
    user-select: none
    transition: color 0.2s ease
    letter-spacing: 0.2px

.message-bubble-wrapper.bubble-sent .message-time-header
  justify-content: flex-end
  padding-right: 8px

.message-bubble-wrapper.bubble-received .message-time-header
  justify-content: flex-start
  padding-left: 8px

.message-bubble
  max-width: 100%
  padding: 8px 12px
  border-radius: 6px
  word-wrap: break-word
  word-break: break-word
  position: relative
  line-height: 1.5
  font-size: 15px
  box-shadow: none

  &.bubble-received
    background: #FFFFFF
    border-bottom-left-radius: 0
    color: #000000
    border: none
    position: relative

  &.bubble-sent
    background: #FFFFFF
    border-bottom-right-radius: 0
    color: #000000
    border: none
    position: relative

  // 图片消息时，减少 padding，让图片更贴近气泡边缘
  &:has(.message-image)
    padding: 4px 4px 8px 4px
  
  // 群聊消息发送者名字样式
  .message-sender-name
    font-size: 12px
    font-weight: 500
    color: rgba(0, 0, 0, 0.6)
    margin-bottom: 4px
    padding: 0 2px

.messages-area
  // 滚动条默认隐藏，悬停时显示
  &::-webkit-scrollbar
    width: 4px
    height: 4px

  &::-webkit-scrollbar-track
    background: transparent
    border-radius: 2px

  &::-webkit-scrollbar-thumb
    background: transparent
    border-radius: 2px
    transition: background 0.3s ease

  // 悬停时显示滚动条
  &:hover::-webkit-scrollbar-thumb
    background: rgba(0, 0, 0, 0.15)

  &::-webkit-scrollbar-thumb:hover
    background: rgba(0, 0, 0, 0.25)

  // 滚动时也显示滚动条（短暂显示）
  &.scrolling::-webkit-scrollbar-thumb
    background: rgba(0, 0, 0, 0.15)
</style>

